/**
 * @file    TestBin.cpp
 * @brief   Binary array data input test
 * @date    2014/02
 * @version
 * Copyright (c)
 */

#include <iostream>
#include "BinInput.cpp"

int main()
{
	{
		// std::string casename = "OilWater";
		// std::string casename = "SPE10";
		std::string casename = "BO3";
		std::cout << "Scanning the binary output file of case \"" << casename << "\"" << std::endl;

		BinReader Rpt;
		Rpt.Scan(casename);

		std::cout << "Overall grid size=" << Rpt.GrossSize()
				  << ", active grid=" << Rpt.NetSize()
				  << ", number of time step=" << Rpt.NStep()
				  << "\n"
				  << std::endl;

		// show all properties
		std::cout << "Grid static properties: " << std::endl;
		for (const Name_Loc &info : Rpt.stat_props)
		{
			std::cout << "Name: " << info.name << "\t";
			std::cout << "Length: " << info.length << "\t";
			std::cout << "Unit: " << info.unit << "\t";
			std::cout << "is at cell center: " << info.on_grid << std::endl;
		}
		////
		// Grid static properties:
		// Name: GRIDINFO	Length: 32	Unit: 	is at cell center: 0
		// Name: PORV	Length: 23124	Unit: rb	is at cell center: 1
		// Name: ROCKV	Length: 23124	Unit: rb	is at cell center: 1
		// Name: XCOORD	Length: 23124	Unit: ft	is at cell center: 1
		// Name: YCOORD	Length: 23124	Unit: ft	is at cell center: 1
		// Name: DEPTH	Length: 23124	Unit: ft	is at cell center: 1
		// Name: DX	Length: 23124	Unit: ft	is at cell center: 1
		// Name: DY	Length: 23124	Unit: ft	is at cell center: 1
		// Name: DZ	Length: 23124	Unit: ft	is at cell center: 1
		// Name: VOLUME	Length: 23124	Unit: ft3	is at cell center: 1
		// Name: NTG	Length: 23124	Unit: 	is at cell center: 1
		// Name: PERMX	Length: 23124	Unit: mD	is at cell center: 1
		// Name: PERMZ	Length: 23124	Unit: mD	is at cell center: 1
		// Name: PORO	Length: 23124	Unit: Frac	is at cell center: 1
		// Name: GRID_VTX	Length: 86544	Unit: ft	is at cell center: 0
		// Name: NODE_LIST	Length: 184992	Unit: 	is at cell center: 0
		// Name: SUBRINFO	Length: 47	Unit: NA	is at cell center: 0
		// Name: N2GMAP	Length: 23124	Unit: NA	is at cell center: 0
		// Name: G2NMAP	Length: 24630	Unit: NA	is at cell center: 0
		// Name: HOSTMAP	Length: 24630	Unit: NA	is at cell center: 0

		{ /* Reservoir grid poly data */
			std::cout << std::endl
					  << "basic xyz postions: " << std::endl;
			double x0, y0, d0;
			Rpt.GetAxisOffset(x0, y0, d0);
			std::cout << "Axis_offset=(" << x0 << ", " << y0 << ", " << d0 << ")" << std::endl;

			PropArray GRID_VTX_array;
			bool find_GRID_VTX = Rpt.GetStaticData("GRID_VTX", GRID_VTX_array);

			//////////// 打印节点数组
			std::cout << std::endl
					  << "## GRID_VTX:" << std::endl;
			if (find_GRID_VTX)
			{
				std::cout << "Find GRID_VTX, length=" << GRID_VTX_array.length << std::endl;
				std::cout << "MAX=" << GRID_VTX_array.Max << "\t";
				std::cout << "MIN=" << GRID_VTX_array.Min << "\t";
				std::cout << "AVG=" << GRID_VTX_array.Avg << "\t" << std::endl;
				std::cout << "data-type=" << GRID_VTX_array.type << "\t";
				std::cout << "time-type=" << GRID_VTX_array.time_type << "\t";
				std::cout << "time=" << GRID_VTX_array.time << "\t";
				std::cout << "data-unit=" << GRID_VTX_array.unit << "\t" << std::endl;
				std::cout << "number of vertex=" << GRID_VTX_array.length / 3 << std::endl;
			}

			std::cout << "data snips 10 examples:" << std::endl;
			for (UGINT64 i = 0; i < GRID_VTX_array.length / 3; i++)
			{
				if (i > 10)
					break;
				std::cout << GRID_VTX_array[i * 3] << " " << GRID_VTX_array[i * 3 + 1] << " " << GRID_VTX_array[i * 3 + 2] << std::endl;
			}

			///////////  打印点集做坐标
			std::cout << std::endl
					  << "## NODE_LIST:" << std::endl;
			PropArray NODE_LIST_array;
			bool find_NODE_LIST = Rpt.GetStaticData("NODE_LIST", NODE_LIST_array);
			if (find_NODE_LIST)
			{
				std::cout << "Find NODE_LIST, length=" << NODE_LIST_array.length << std::endl;
				std::cout << "MAX=" << NODE_LIST_array.Max << "\t";
				std::cout << "MIN=" << NODE_LIST_array.Min << "\t";
				std::cout << "AVG=" << NODE_LIST_array.Avg << "\t" << std::endl;
				std::cout << "data-type=" << NODE_LIST_array.type << "\t";
				std::cout << "time-type=" << NODE_LIST_array.time_type << "\t";
				std::cout << "time=" << NODE_LIST_array.time << "\t";
				std::cout << "data-unit=" << NODE_LIST_array.unit << "\t" << std::endl;

				std::cout << "data snips 10 examples:" << std::endl;
				for (UGINT64 i = 0; i < NODE_LIST_array.length / 8; i++)
				{
					if (i > 10)
						break;
					for (UGINT64 j = 0; j < 8; j++)
					{
						std::cout << NODE_LIST_array[i * 8 + j] << " ";
					}
					std::cout << std::endl;
				}
			}

			if (Rpt.GridType() < 3 && find_GRID_VTX && find_NODE_LIST)
			{
				UGINT64 n_visible_elm = NODE_LIST_array.length / 8;
				std::cout << "\nCorner point grid poly data are complete" << std::endl;
				std::cout << "NI=" << Rpt.SGridNI() << "\t";
				std::cout << "NJ=" << Rpt.SGridNJ() << "\t";
				std::cout << "NK=" << Rpt.SGridNK() << "\t";
				std::cout << "NLayer=" << Rpt.SGridNK() / Rpt.PoroLvl() << "\t";
				std::cout << "PoroLvl=" << Rpt.PoroLvl() << "\t";
				std::cout << "number of visible element =length(NODE_LIST)/8 =" << n_visible_elm << "\n"
						  << std::endl;
			}

			PropArray PORV_array;
			PropArray XCOORD_array;
			PropArray YCOORD_array;
			PropArray DEPTH_array;
			PropArray DX_array;
			PropArray DY_array;
			PropArray DZ_array;
			PropArray VOLUME_array;
			// PropArray NTG_array;
			PropArray PERMX_array;
			PropArray PERMZ_array;
			PropArray PORO_array;

			bool find_PORV = Rpt.GetStaticData("PORV", PORV_array);
			bool find_XCOORD = Rpt.GetStaticData("XCOORD", XCOORD_array);
			bool find_YCOORD = Rpt.GetStaticData("YCOORD", YCOORD_array);
			bool find_DEPTH = Rpt.GetStaticData("DEPTH", DEPTH_array);
			bool find_DX = Rpt.GetStaticData("DX", DX_array);
			bool find_DY = Rpt.GetStaticData("DY", DY_array);
			bool find_DZ = Rpt.GetStaticData("DZ", DZ_array);
			bool find_VOLUME = Rpt.GetStaticData("VOLUME", VOLUME_array);
			// bool find_NTG = Rpt.GetStaticData("NTG", NTG_array);
			bool find_PERMX = Rpt.GetStaticData("PERMX", PERMX_array);
			bool find_PORO = Rpt.GetStaticData("PORO", PORO_array);
			bool find_PERMZ = Rpt.GetStaticData("PERMZ", PERMZ_array);

			if ((find_PORV && find_XCOORD && find_YCOORD && find_DEPTH) &&
				(find_DX && find_DY && find_DZ) &&
				(find_VOLUME && find_PERMX) &&
				(find_PORO && find_PERMZ))
			{
				std::cout << "find all static properties" << std::endl;
			}
			else
			{
				std::cout << "not find all static properties" << std::endl;
			}

			// save all nodes
			std::ofstream fs_node("0_nodes_" + casename + ".txt", std::ios::out | std::ios::app);
			for (UGINT64 i = 0; i < GRID_VTX_array.length / 3; i++)
			{
				for (UGINT64 j = 0; j < 3; j++)
				{
					fs_node << GRID_VTX_array[i * 3 + j] << ",";
				}
				fs_node << std::endl;
			}
			fs_node.close();

			// save box with 8 nodes
			std::ofstream fs_box("0_boxs_" + casename + ".txt", std::ios::out | std::ios::app);
			for (UGINT64 i = 0; i < NODE_LIST_array.length / 8; i++)
			{
				for (UGINT64 j = 0; j < 8; j++)
				{
					fs_box << NODE_LIST_array[i * 8 + j] << ",";
				}
				fs_box << std::endl;
			}
			fs_box.close();

			// save file
			std::ofstream fs("0_data_" + casename + ".csv", std::ios::out | std::ios::app);
			std::ofstream fs_properties("0_properties_" + casename + ".csv", std::ios::out | std::ios::app);

			// save header
			fs << "nodeid,x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,x5,y5,z5,x6,y6,z6,x7,y7,z7,x8,y8,z8,"
			   //    << "porv,xcoord,ycoord,dx,dy,dz,volume,permx,poro,permz,depth"
			   << "permx,poro"
			   << std::endl;

			for (UGINT64 i = 0; i < NODE_LIST_array.length / 8; i++)
			{

				UGINT64 poiters[8];
				// std::cout << "i=" << i << std::endl;
				fs << i << ",";

				for (UGINT64 j = 0; j < 8; j++)
				{
					poiters[j] = NODE_LIST_array[i * 8 + j];
					UGINT64 node_id = NODE_LIST_array[i * 8 + j];

					if (i < 3)
					{
						std::cout << node_id << ","
								  << GRID_VTX_array[node_id * 3 + 1] << ","
								  << GRID_VTX_array[node_id * 3 + 2] << ","
								  << GRID_VTX_array[node_id * 3 + 3] << std::endl;
					}

					fs << GRID_VTX_array[node_id * 3 + 1] << ","
					   << GRID_VTX_array[node_id * 3 + 2] << ","
					   << GRID_VTX_array[node_id * 3 + 3] << ",";
				}

				// property
				if (i < 3)
				{
					std::cout << "PORV:" << PORV_array[i] << "\t"
							  << "XCOORD:" << XCOORD_array[i] << "\t"
							  << "YCOORD:" << YCOORD_array[i] << "\t"
							  << "DX:" << DX_array[i] << "\t"
							  << "DY:" << DY_array[i] << "\t"
							  << "DZ:" << DZ_array[i] << "\t"
							  << "VOLUME:" << VOLUME_array[i] << "\t"
							  << "PERMX:" << PERMX_array[i] << "\t"
							  << "PORO:" << PORO_array[i] << "\t"
							  << "PERMZ:" << PERMZ_array[i] << "\t"
							  << "DEPTH:" << DEPTH_array[i] << std::endl;
				}

				// fs << PORV_array[i] << ","
				//    << XCOORD_array[i] << ","
				//    << YCOORD_array[i] << ","
				//    << DX_array[i] << ","
				//    << DY_array[i] << ","
				//    << DZ_array[i] << ","
				//    << VOLUME_array[i] << ","
				//    << PERMX_array[i] << ","
				//    << PORO_array[i] << ","
				//    << PERMZ_array[i] << ","
				//    << DEPTH_array[i] << std::endl;
				fs << PERMX_array[i] << ","
				   << PORO_array[i] << std::endl;

				fs_properties
					<< PERMX_array[i] << ","
					<< PORO_array[i] << ","
					<< std::endl;
			}

			fs.close();

			std::cout << std::endl
					  << "## PROPERTIES:" << std::endl;
		}

		std::cout << "\nPress any key to quit" << std::endl;
	}
	return 0;
}